package handler

import (
	"encoding/json"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"log"
	"net/http"
	"time"
	"zy10/api/request"
	"zy10/internal/dao"
	"zy10/internal/model"
)

/**
{
    "cmd":"send",
    "data":{
        "to_user_id": 2,
        "message":"hello 2"
    }
}

{
    "cmd":"sendGroup",
    "data":{
        "message":"all"
    }
}
*/

var OnlineUser = make(map[uint]*websocket.Conn)

type WSReq struct {
	Cmd  string      `json:"cmd"`
	Data interface{} `json:"data"`
}

type WSResp struct {
	Code uint        `json:"code"`
	Msg  string      `json:"msg"`
	Data interface{} `json:"data"`
}

type SendS struct {
	CType    uint   `json:"c_type"`
	ToUserId uint   `json:"to_user_id"`
	Message  string `json:"message"`
}

type WSSendReq struct {
	Cmd  string `json:"cmd"`
	Data SendS  `json:"data"`
}

type GroupS struct {
	Message string `json:"message"`
}

type WSGroupReq struct {
	Cmd  string `json:"cmd"`
	Data GroupS `json:"data"`
}

func Chat(c *gin.Context) {

	//get params test
	//userIdStr, _ := c.GetQuery("userId")
	//var userId uint
	//userIdInt, _ := strconv.Atoi(userIdStr)
	//userId = uint(userIdInt)

	//get middle userId
	userId := c.GetUint("userId")

	// update websocket
	var upgrader = websocket.Upgrader{} // use default options

	conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		log.Print("upgrade:", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "websocket fail",
			"data": nil,
		})
		return
	}

	defer conn.Close()

	go func() {
		// 30s
		WSRespSuccess(conn, "HMY")
		for {
			err := conn.WriteMessage(websocket.PingMessage, []byte("HMY"))

			if err != nil {
				delete(OnlineUser, userId)
				return
			}

			time.Sleep(30 * time.Second)
		}
	}()

	//online user data
	OnlineUser[userId] = conn
	log.Println(OnlineUser)
	for {
		_, message, err := conn.ReadMessage()
		if err != nil {
			log.Println("read:", err)
			break
		}

		var req WSReq

		err = json.Unmarshal(message, &req)
		if err != nil {

			WSRespErr(conn, 1000, "illegal json")
			continue
		}

		switch req.Cmd {
		case "send":
			go Send(conn, message, userId)
		case "sendGroup":
			go SendGroup(conn, message, userId)
		default:
			WSRespErr(conn, 10001, "no function")
		}

	}
}

func SendGroup(conn *websocket.Conn, message []byte, userId uint) {
	var req WSGroupReq
	err := json.Unmarshal(message, &req)
	if err != nil {
		WSRespErr(conn, 20001, "Parsing json failed ")
		return
	}

	if req.Data.Message == "" {
		WSRespErr(conn, 20004, "not Message params")
		return
	}

	if len(OnlineUser) == 0 {
		WSRespErr(conn, 20002, "not Online user")
		return
	}

	for _, onlineConn := range OnlineUser {

		WSRespSuccess(onlineConn, req.Data.Message)

	}
}

func Send(conn *websocket.Conn, message []byte, userId uint) {

	var req WSSendReq
	err := json.Unmarshal(message, &req)
	if err != nil {
		WSRespErr(conn, 20001, "Parsing json failed ")
		return
	}

	if req.Data.ToUserId < 1 {
		WSRespErr(conn, 20002, "not ToUserId params")
		return
	}

	if req.Data.Message == "" {
		WSRespErr(conn, 20004, "not Message params")
		return
	}

	if OnlineUser[req.Data.ToUserId] == nil {
		WSRespErr(conn, 20003, "not online")
		return
	}

	WSRespSuccess(OnlineUser[req.Data.ToUserId], req.Data.Message)
	dao.Create(&model.ChatHistory{

		FormUserId: userId,
		ToUserId:   req.Data.ToUserId,
		RoomId:     GetRoomId(userId, req.Data.ToUserId),
		CType:      req.Data.CType,
		Content:    req.Data.Message,
	})
	WSRespSuccess(conn, "send ok")

}

func GetRoomId(min uint, max uint) uint {
	if min > max {
		tou := max
		max = min
		min = tou
	}
	return min*10000 + max
}

func WSRespErr(conn *websocket.Conn, code uint, msg string) {
	response := WSResp{
		Code: code,
		Msg:  msg,
		Data: nil,
	}

	responseStr, _ := json.Marshal(response)

	err := conn.WriteMessage(websocket.TextMessage, responseStr)
	if err != nil {
		log.Println("write:", err)
	}
}

func WSRespSuccess(conn *websocket.Conn, data interface{}) {
	response := WSResp{
		Code: 0,
		Msg:  "ok",
		Data: data,
	}

	responseStr, _ := json.Marshal(response)

	err := conn.WriteMessage(websocket.TextMessage, responseStr)
	if err != nil {
		log.Println("write:", err)
	}
}

func CreateChatRoom(c *gin.Context) {
	var req request.CreateChatRoomReq
	if err := c.ShouldBind(&req); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": 1000,
			"msg":  "验证失败",
			"data": nil,
		})
		return
	}
	var room model.ChatGroup
	room = model.ChatGroup{

		UserId: c.GetUint("userId"),
		Name:   req.Name,
	}
	if !dao.Create(&room) {
		c.JSON(http.StatusOK, gin.H{
			"code": 1000,
			"msg":  "创建聊天室失败",
			"data": nil,
		})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "创建聊天室成功",
		"data": room,
	})

	result := dao.Create(&model.ChatGroupUser{
		GroupUserId: room.UserId,
		Level:       1,
		GroupId:     room.Id,
	})
	if !result {
		c.JSON(http.StatusOK, gin.H{
			"code": 1000,
			"msg":  "聊天室拉取失败",
			"data": nil,
		})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "聊天室拉取成功",
		"data": result,
	})

}

func AddUserId(c *gin.Context) {
	var req request.AddChatRoomReq
	if err := c.ShouldBind(&req); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": 1000,
			"msg":  "验证失败",
			"data": nil,
		})
		return
	}
	var room model.ChatGroup
	dao.GetOneById(req.GroupId, &room)
	if room.Id == 0 {
		c.JSON(http.StatusOK, gin.H{
			"code": 1000,
			"msg":  "聊天室不存在",
			"data": nil,
		})
		return
	}
	for _, u := range req.GroupUserId {
		var user model.User
		dao.GetOneById(u, &user)
		if user.Id == 0 {
			c.JSON(http.StatusOK, gin.H{
				"code": 1000,
				"msg":  "该用户不存在",
				"data": nil,
			})
			return
		}
	}
	var groupUser model.ChatGroupUser
	dao.GetOneByFields(&model.ChatGroupUser{
		GroupUserId: c.GetUint("userId"),

		GroupId: req.GroupId,
	}, &groupUser)

	if groupUser.Id == 0 {
		c.JSON(http.StatusOK, gin.H{
			"code": 1000,
			"msg":  "该用户不存在",
			"data": nil,
		})
		return
	}
	//groupUser = model.ChatGroupUser{
	//
	//	GroupUserId: c.GetUint("userId"),
	//
	//	GroupId: req.GroupId,
	//}
	//if groupUser.Id == 0 {
	//	c.JSON(http.StatusOK, gin.H{
	//		"code": 1000,
	//		"msg":  "群聊成员不存在",
	//		"data": nil,
	//	})
	//	return
	//}
	if groupUser.Level != 1 && groupUser.Level != 2 {
		c.JSON(http.StatusOK, gin.H{
			"code": 1000,
			"msg":  "当前没有权限拉人",
			"data": nil,
		})
		return
	}
	for _, u := range req.GroupUserId {
		var groupUser model.ChatGroupUser
		dao.GetOneByFields(&model.ChatGroupUser{

			GroupUserId: u,

			GroupId: req.GroupId,
		}, &groupUser)
	}
	if groupUser.Id == 0 {
		c.JSON(http.StatusOK, gin.H{
			"code": 1000,
			"msg":  "群成员不存在",
			"data": nil,
		})
		return
	}
	for _, u := range req.GroupUserId {
		dao.Create(&model.ChatGroupUser{
			GroupUserId: u,

			GroupId: req.GroupId,
		})

	}

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "进入聊天室成功",
		"data": true,
	})
}
